// promise 是一个类
// promise 有三个状态 等待 成功 失败

const PENDING = "pending";
const RESOLVED = "resolved";
const REJECTED = "rejected";
const resolvePromise = (promise2, result, resolve, reject) => {
  //判断result的值个promise2是不是同一个，同一个就不等待了
  if (promise2 === result) {
    return reject(
      new TypeError("promise can not return oneself (不能返回自身)")
    );
  }
  //如果result 是一个object 或者 function
  if (
    (typeof result === "object" && result !== null) ||
    typeof result === "function"
  ) {
    let called; // 内部测试的时候 成功失败都调用
    try {
      let then = result.then; //这里try catch 是因为有可能是别人的promise内部抛出错误
      if (typeof then === "function") {
        //如果有then 我就姑且认为他是一个Promise
        //result.then() 不这样写的原因是有可能之前取then没报错，现在取then会报错
        //严谨写法 不用再次取then
        then.call(
          result,
          (y) => {
            // y有可能又是一个promise 直到解析出来的结果是一个普通值为止
            if (called) {
              return;
            }
            called = true;
            resolvePromise(promise2, y, resolve, reject); //采用promise成功的结果向下传递
          },
          (r) => {
            if (called) {
              return;
            }
            called = true;
            reject(r); //采用promise失败的结果向下传递
          }
        );
      } else {
        //如果then不是promise
        resolve(result);
      }
    } catch (e) {
      if (called) {
        return;
      }
      called = true;
      reject(e);
    }
  } else {
    //如果不是function
    resolve(result);
  }
};
class Promise {
  constructor(executor) {
    this.status = PENDING; // 默认是pending状态
    this.value = undefined; //成功的值
    this.reason = undefined; //失败的原因
    this.onResolvedCallbacks = []; // 成功的回调数组
    this.onRejectedCallbacks = []; // 失败的回调数组
    //成功状态的回调函数
    const resolve = (value) => {
      //屏蔽调用 resolve和reject只能执行一方
      if (this.status === PENDING) {
        this.value = value;
        this.status = RESOLVED;
        this.onResolvedCallbacks.forEach((fn) => fn()); //发布
      }
    };
    //失败状态的回调函数
    const reject = (reason) => {
      //屏蔽调用 resolve和reject只能执行一方
      if (this.status === PENDING) {
        this.reason = reason;
        this.status = REJECTED;
        this.onRejectedCallbacks.forEach((fn) => fn()); //发布
      }
    };
    try {
      executor(resolve, reject); //执行器 默认立即执行
    } catch (e) {
      reject(e);
    }
  }
  then(onresolved, onrejected) {
    // onresolved,onrejected 是可选参数
    onresolved = typeof onresolved === "function" ? onresolved : (data) => data;
    onrejected =
      typeof onrejected === "function"
        ? onrejected
        : (err) => {
            throw err;
          };
    //then的链式调用，每次都返回一个新promise
    const promise2 = new Promise((resolve, reject) => {
      //executor会立即执行
      //同步情况
      if (this.status === RESOLVED) {
        //res可能是普通值，也可能是promise类型
        setTimeout(() => {
          try {
            //宏任务
            //获取then里面return的值，
            const res = onresolved(this.value);
            //判断res的值，推断promise2的状态
            //再次包装到promise里面
            //由于获取不到promise2，所以加个定时器
            resolvePromise(promise2, res, resolve, reject);
          } catch (e) {
            reject(e);
          }
        }, 0);
      }
      if (this.status === REJECTED) {
        setTimeout(() => {
          try {
            const err = onrejected(this.reason);
            resolvePromise(promise2, err, resolve, reject);
          } catch (e) {
            reject(e);
          }
        }, 0);
      }
      //异步情况
      if (this.status === PENDING) {
        // 如果是异步，先订阅
        this.onResolvedCallbacks.push(() => {
          setTimeout(() => {
            try {
              const res = onresolved(this.value);
              resolvePromise(promise2, res, resolve, reject);
            } catch (e) {
              reject(e);
            }
          }, 0);
        });
        this.onRejectedCallbacks.push(() => {
          setTimeout(() => {
            try {
              const err = onrejected(this.reason);
              resolvePromise(promise2, err, resolve, reject);
            } catch (e) {
              reject(e);
            }
          }, 0);
        });
      }
    });
    return promise2;
  }
  static all() {}
}

module.exports = Promise;
